package com.he.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.he.constant.RedisConstant;
import com.he.domain.dto.ConditionDTO;
import com.he.domain.dto.PageResult;
import com.he.domain.dto.TagDTO;
import com.he.domain.vo.*;
import com.he.entity.ArticleTag;
import com.he.entity.Tag;
import com.he.mapper.ArticleMapper;
import com.he.mapper.ArticleTagMapper;
import com.he.mapper.TagMapper;
import com.he.service.RedisService;
import com.he.service.TagService;
import com.he.utils.BeanCopyUtils;
import com.he.utils.PageUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author He
 * @version 1.0
 * @Date 2023/9/17 17:09
 * @Desc 标签Service实现类
 */
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements TagService {

    @Resource
    private TagMapper tagMapper;

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private ArticleTagMapper articleTagMapper;

    @Override
    public List<TagVO> listTagVO() {
        return tagMapper.getTagList();
    }

    @Override
    public ArticleConditionList listArticleTag(ConditionDTO condition) {
        if(condition.getTagId() == null)
        {
            return ArticleConditionList.builder()
                    .articleConditionVOList(Collections.emptyList())
                    .name("")
                    .build();
        }
        // redi获取标签下的文章信息
        List<ArticleConditionVO> articleConditionVOS = redisService.getHash(RedisConstant.TAG_ARTICLE_LIST,
                 condition.getTagId().toString());
        if(Objects.isNull(articleConditionVOS))
        {
            //重新查标签对应文章信息
            articleConditionVOS = articleMapper.listArticleByCondition(PageUtils.getLimit(), PageUtils.getSize(), condition);
            articleConditionVOS =  articleConditionVOS.stream()
                    .map(
                            articleConditionVO -> {
                                //设置文章标签
                                List<TagOptionVO> tagOptionVOS = tagMapper.selectArticleTags(articleConditionVO.getId());
                                articleConditionVO.setTagVOList(tagOptionVOS);
                                //设置文章浏览量
                                Double viewCount = redisService.getZsetScore(RedisConstant.ARTICLE_VIEW_COUNT, articleConditionVO.getId());
                                articleConditionVO.setArticleViews(viewCount == null ? 0 : viewCount.intValue());
                                return articleConditionVO;
                            }
                    ).collect(Collectors.toList());
            redisService.setHash(RedisConstant.TAG_ARTICLE_LIST, condition.getTagId().toString(), articleConditionVOS);
        }else {
            articleConditionVOS.stream()
                    .map(
                            articleConditionVO -> {
                                Double viewCount = redisService.getZsetScore(RedisConstant.ARTICLE_VIEW_COUNT, articleConditionVO.getId());
                                articleConditionVO.setArticleViews(viewCount == null ? 0 : viewCount.intValue());
                                return articleConditionVO;
                            }
                    ).collect(Collectors.toList());
        }
        return ArticleConditionList.builder()
                .articleConditionVOList(articleConditionVOS)
                .name("")
                .build();
    }

    @Override
    public List<String> existTagNames(List<String> tagNames) {
        if(tagNames.isEmpty())
        {
            return Collections.emptyList();
        }
        List<String> tagNamesList = listObjs(new LambdaQueryWrapper<>(Tag.class)
                .select(Tag::getTagName)
                .in(Tag::getTagName, tagNames), obj -> (String) obj);
        if (tagNamesList.isEmpty()) {
            return Collections.emptyList();
        }
        return tagNamesList;
    }

    @Override
    public List<TagOptionVO> listTagOption() {
        List<Tag> list = list();
        return BeanCopyUtils.copyBeanList(list, TagOptionVO.class);
    }

    @Override
    public PageResult<TagBackVO>  listTagBackVO(ConditionDTO condition) {
        // 查询标签数量
        Long count = tagMapper.selectCount(new LambdaQueryWrapper<Tag>()
                .like(StringUtils.hasText(condition.getKeyword()), Tag::getTagName,
                        condition.getKeyword()));
        if (count == 0) {
            return new PageResult<>();
        }
        // 分页查询标签列表
        List<TagBackVO> tagList = tagMapper.selectTagBackVO(PageUtils.getLimit(), PageUtils.getSize(), condition.getKeyword());
        return new PageResult<>(tagList, count);
    }

    @Override
    public void addTag(TagDTO tag) {
        // 标签是否存在
        Tag existTag = tagMapper.selectOne(new LambdaQueryWrapper<Tag>()
                .select(Tag::getId)
                .eq(Tag::getTagName, tag.getTagName().trim()));
        Assert.isNull(existTag, tag.getTagName() + "标签已存在");
        // 添加新标签
        Tag newTag = Tag.builder()
                .tagName(tag.getTagName())
                .build();
        baseMapper.insert(newTag);
    }

    @Override
    public void deleteTag(List<Integer> tagIdList) {
        // 标签下是否有文章
        Long count = articleTagMapper.selectCount(new LambdaQueryWrapper<ArticleTag>()
                .in(ArticleTag::getTagId, tagIdList));
        Assert.isFalse(count > 0, "删除失败，标签下存在文章");
        // 批量删除标签
        tagMapper.deleteBatchIds(tagIdList);
    }

    @Override
    public void updateTag(TagDTO tag) {
        // 标签是否存在
        Tag existTag = tagMapper.selectOne(new LambdaQueryWrapper<Tag>()
                .select(Tag::getId)
                .eq(Tag::getTagName, tag.getTagName().trim()));
        Assert.isFalse(Objects.nonNull(existTag) && !existTag.getId().equals(tag.getId()),
                tag.getTagName() + "标签已存在");
        // 修改标签
        Tag newTag = Tag.builder()
                .id(tag.getId())
                .tagName(tag.getTagName())
                .build();
        baseMapper.updateById(newTag);
    }


}
